TextField 包裝組件是一個完整的表單控件,包括標籤、輸入和幫助文本,它支持標準、輪廓和填充樣式。簡單來說它是一個整合了 FormControl, InputLabel, Input, FormHelperText 的綜合組件,從原生的 html 標籤來看,它確實是使用了 fieldset 來整合整個 input 輸入框的樣式,這也是它會命名為text field的原因吧。
以下兩種寫法是相同的
<TextField id="textfield" label="Standard" />
<FormControl>
<InputLabel htmlFor="form-control">Form Control</InputLabel>
<Input id="form-control" />
</FormControl>
在基礎引入狀態下的 variant 有以下三種,預設值為 standard:
<form noValidate autoComplete="off">
<TextField id="standard-basic" label="Standard" />
<TextField id="filled-basic" label="Filled" variant="filled" />
<TextField id="outlined-basic" label="Outlined" variant="outlined" />
</form>
也支援一些基本的表單屬性,例如:required, disabled, type...等等,也包含了helperText,通常用來描述如何使用這個輸入框。
<TextField
required
id="standard-required"
label="Required"
defaultValue="Hello World"
/>
<TextField
disabled
id="standard-disabled"
label="Disabled"
defaultValue="Hello World"
/>
<TextField
id="standard-password-input"
label="Password"
type="password"
autoComplete="current-password"
/>
<TextField
id="standard-read-only-input"
label="Read Only"
defaultValue="Hello World"
InputProps={{
readOnly: true,
}}
/>
<TextField
id="standard-number"
label="Number"
type="number"
InputLabelProps={{
shrink: true,
}}
/>
<TextField id="standard-search" label="Search field" type="search" />
<TextField
id="standard-helperText"
label="Helper text"
defaultValue="Default Value"
helperText="Some important text"
/>
可以使用 error 來切換錯誤的狀態,同時也可使用 helperText 來給用戶提供錯誤提示訊息。
<TextField
variant="filled"
error
label="Error"
defaultValue="Hello World"
helperText="Incorrect entry."
/>
錯誤的部分可以按個人喜好選擇搭配 formik 或是 react-hook-form 來做檢核,之後會做詳細的講解如何與 react-hook-form 做搭配。
使用 multiline,能將原本的輸入框轉換成多行,類似 textarea 的特性,簡單來說就是 textarea 更換皮膚。
<TextField
label="Multiline"
multiline
maxRows={4}
value={value}
onChange={handleChange}
/>
<TextField
label="Multiline Placeholder"
variant="filled"
placeholder="Placeholder"
multiline
/>
<TextField
label="Multiline"
variant="outlined"
multiline
rows={4}
defaultValue="Default Value"
/>
使用 select 可以在輸入框内插入一個 Select 組件,不過通常會直接使用 Select 組件來處理:
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import MenuItem from '@material-ui/core/MenuItem';
const currencies = [
{
value: 'USD',
label: '$',
},
{
value: 'EUR',
label: '€',
},
{
value: 'BTC',
label: '฿',
},
{
value: 'JPY',
label: '¥',
},
];
const useStyles = makeStyles((theme) => ({
root: {
'& .MuiTextField-root': {
margin: theme.spacing(1),
width: '25ch',
},
},
}));
export default function MultilineTextFields() {
const classes = useStyles();
const [currency, setCurrency] = React.useState('EUR');
const handleChange = (event) => {
setCurrency(event.target.value);
};
return (
<form className={classes.root} noValidate autoComplete="off">
<div>
<TextField
id="standard-select-currency"
select
label="Select"
value={currency}
onChange={handleChange}
helperText="Please select your currency"
>
{currencies.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField
id="standard-select-currency-native"
select
label="Native select"
value={currency}
onChange={handleChange}
SelectProps={{
native: true,
}}
helperText="Please select your currency"
>
{currencies.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
</div>
<div>
<TextField
id="filled-select-currency"
select
label="Select"
value={currency}
onChange={handleChange}
helperText="Please select your currency"
variant="filled"
>
{currencies.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField
id="filled-select-currency-native"
select
label="Native select"
value={currency}
onChange={handleChange}
SelectProps={{
native: true,
}}
helperText="Please select your currency"
variant="filled"
>
{currencies.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
</div>
<div>
<TextField
id="outlined-select-currency"
select
label="Select"
value={currency}
onChange={handleChange}
helperText="Please select your currency"
variant="outlined"
>
{currencies.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField
id="outlined-select-currency-native"
select
label="Native select"
value={currency}
onChange={handleChange}
SelectProps={{
native: true,
}}
helperText="Please select your currency"
variant="outlined"
>
{currencies.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
</div>
</form>
);
}
可用於向輸入框添加前綴、後缀或動作。 例如,可以用一個icon或按鈕來隱藏或者顯示輸入框內的密碼範例。
<TextField
label="加入前綴"
id="standard-start-adornment"
InputProps={{
startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
}}
/>
<TextField
label="加入後綴"
id="standard-end-adornment"
InputProps={{
startAdornment: <InputAdornment position="end">Kg</InputAdornment>,
}}
/>
使用 margin 屬性,你可以改變數入框的垂直間距。 若您使用 none (預設值),將不會在 FormControl 上添加間距,相對的,使用 dense 和 normal 會添加間距。
fullWidth 属性,使用它時,輸入框會占滿整個容器的寬度。
<TextField
id="outlined-full-width"
label="Label"
style={{ margin: 8 }}
placeholder="Placeholder"
helperText="Full width!"
fullWidth
margin="normal"
InputLabelProps={{
shrink: true,
}}
variant="outlined"
/>
<TextField
label="None"
id="outlined-margin-none"
defaultValue="Default Value"
className={classes.textField}
helperText="Some important text"
variant="outlined"
/>
<TextField
label="Dense"
id="outlined-margin-dense"
defaultValue="Default Value"
className={classes.textField}
helperText="Some important text"
margin="dense"
variant="outlined"
/>
<TextField
label="Normal"
id="outlined-margin-normal"
defaultValue="Default Value"
className={classes.textField}
helperText="Some important text"
margin="normal"
variant="outlined"
/>
輸入框標籤的 "shrink" 狀態不正確,標籤應在輸入框顯示内容的時候立即收縮。 在某些情況下,我們無法確定輸入框的 "shrink" 狀態(如數字、日期時間)如此便有可能出現重疊。
若要解決此問題,可以在輸入框的標籤上强制給予 "shrink" 狀態。
<TextField InputLabelProps={{ shrink: true }} />
或
<InputLabel shrink>hello</InputLabel>
至此今天大致講解完基本的應用了,明天會接續講解 date/time picker 日期輸入的部分。